/**
 * @author yunfengb
 * 
 * 2013-4-10
 */
package collision;

import java.util.HashSet;

import geometry.Drawable;
import geometry.Triangle;
import geometry.Triangle.ClosestPointInfo;
import geometry.TriangleMesh;

import javax.media.opengl.GL2;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

public class OBBTree extends BoundingVolume {
	protected OBBTreeNode root;
	protected Drawable geometry;
	protected long tick;
	protected Matrix4d toWorldSpaceMatrix, toModelSpaceMatrix;
	
	public OBBTree() {}
	
	public OBBTree(Drawable geometry)
	{
		this.geometry = geometry;
		root = new OBBTreeNode(this);
		root.buildTree(0, geometry.getTriangleMesh()._triangles);
	}

	public double getSignedDistance(Point3d point) {
		return root.getSignedDistance(point);
	}

	public ClosestPointInfo getClosestPoint(Point3d point) {
		return root.getClosestPoint(point);
	}

	public boolean isIntersectedWithOBB(OBB AABB) {
		return root.isIntersectedWithOBB(AABB);
	}

	public void updateTransform(Matrix4d transformMatrix,
			Matrix4d transformMatrixInv) {
		tick++;
		
		toWorldSpaceMatrix = new Matrix4d();
		toWorldSpaceMatrix.set(transformMatrix);
		toModelSpaceMatrix = new Matrix4d();
		toModelSpaceMatrix.set(transformMatrixInv);
	}

	public void draw(GL2 gl) {
		root.draw(gl);
	}

	@Override
	public boolean isColliding(BoundingVolume obj_) {
		if (!(obj_ instanceof OBBTree))
			throw new IllegalArgumentException("OBBTree can only collide with OBBTree");
		
		return root.isColliding(((OBBTree)obj_).root);
	}

	@Override
	public void build(GL2 gl) {
		root.build(gl);
	}

	@Override
	public TriangleMesh getTriangleMesh() {
		throw new NotImplementedException();
	}

	@Override
	public BoundingBox getBoundingBox() {
		throw new NotImplementedException();
	}

	public void collide(OBBTree tree2, HashSet<Triangle> triangles1,
			HashSet<Triangle> triangles2) {
		root.collide(tree2.root, triangles1, triangles2);
	}
	
	public OBB getRootOBB()
	{
		return root.getOBB();
	}
	
	long getTick()
	{
		return tick;
	}
	
	Matrix4d getToWorldSpaceMatrix()
	{
		return toWorldSpaceMatrix;
	}
	
	Matrix4d getToModelSpaceMatrix()
	{
		return toModelSpaceMatrix;
	}
}
